﻿#ifndef CHTTPCLIENT_H
#define CHTTPCLIENT_H
#include <typeinfo>
#include <string>
#include <curl/curl.h>
#include <string>
#include <vector>
#include <map>
#include "publicfun/condmutex.h"
#include "publicfun/public.h"
#include "rawstr.h"
#include <string.h>
#ifdef __linux
#include <alloca.h>
#define strtok_s strtok_r
#endif
#include <time.h>
#include <stdlib.h>
using namespace std;

typedef void (*CALLBACKFUN)(CURL*);
//curl_easy_setopt(curl, CURLOPT_COOKIEJAR, "/tmp/getskypecookie.txt");
//curl_easy_setopt(curl, CURLOPT_HEADER, 1);          //下载数据包括HTTP头部
//curl_easy_setopt(curl_, CURLOPT_FOLLOWLOCATION, 1L);  
//curl_easy_setopt(curl_, CURLOPT_ACCEPT_ENCODING, "gzip");
//

string GetSysProxy(const std::string& strURL);

//copy from curl
inline bool tailmatch(const char *cooke_domain, const char *hostname)
{
  size_t cookie_domain_len = strlen(cooke_domain);
  size_t hostname_len = strlen(hostname);

  if(hostname_len < cookie_domain_len)
    return false;

  if(!Curl_raw_equal(cooke_domain, hostname+hostname_len-cookie_domain_len))
    return false;

  /* A lead char of cookie_domain is not '.'.
     RFC6265 4.1.2.3. The Domain Attribute says:
       For example, if the value of the Domain attribute is
       "example.com", the user agent will include the cookie in the Cookie
       header when making HTTP requests to example.com, www.example.com, and
       www.corp.example.com.
   */
  if(hostname_len == cookie_domain_len)
    return true;
  if('.' == *(hostname + hostname_len - cookie_domain_len - 1))
      return true;
  return false;
}

/*pass a http header string to this*/
//https://www.rfc-editor.org/rfc/rfc6265.txt
struct cookieLine {
    string key;
    string value;
    string expirestr;  /* the plain text version */
    string path;
    string domain;/* domain = <this> */

    char *spath;        /* sanitized cookie path */
    time_t expires;  /* expires = <this> */
    bool tailmatch;    /* weather we do tail-matchning of the domain name */

    /* RFC 2109 keywords. Version=1 means 2109-compliant cookie sending */
    string version;     /* Version = <value> */
    string maxage;      /* Max-Age = <value> */

    bool secure;       /* whether the 'secure' keyword was used */
    bool livecookie;   /* updated from a server, not a stored file */
    bool httponly;     /* true if the httponly directive is present */
};

#define MAX_COOKIE_LINE 5000
#define MAX_COOKIE_LINE_TXT "4999"

/* This is the maximum length of a cookie name we deal with: */
#define MAX_NAME 1024
#define MAX_NAME_TXT "1023"

#define CURL_OFF_T_MAX  0x7FFFFFFF

struct Cookie_S:public vector<cookieLine *>{
    ~Cookie_S(){
        for(Cookie_S::iterator i = this->begin(); i != this->end(); ++i){
            if(*i){
                delete(*i);
            }
        }
        clear();
    }

    Cookie_S & operator=(const char * parm){
        for(Cookie_S::iterator i = this->begin(); i != this->end(); ++i){
            if(*i){
                delete(*i);
            }
        }
        clear();
        parse(parm);
        return *this;
    }

    Cookie_S(const char *p){
        parse(p);
    }
    Cookie_S(){}
private:
    //Set-Cookie:
    //uaid=d9222f1ae636ae8efc6c6635d13e2f7f;domain=login.live.com;secure=;path=/;HTTPOnly=;version=1

    inline int dealapair(cookieLine *cl, const char *lowkey, const char *key, const char *value)
    {
        int ret = 0;
        time_t now = time(NULL);

        if(strcmp(lowkey, "domain") == 0){
            if(*(value) == '.'){
                cl->domain = value + 1;
            }else{
                cl->domain = value;
            }
        }else if(strcmp(lowkey, "secure") == 0){
            cl->secure = true;
        }else if(strcmp(lowkey, "path") == 0){
            cl->path = value;
        }else if(strcmp(lowkey, "version") == 0){
            cl->version = value;
        } else if (strcmp(lowkey, "httponly") == 0) {
            cl->httponly = true;
        } else if(strcmp(lowkey, "expires") == 0){
            cl->expirestr = value;
            /* Note that if the date couldn't get parsed for whatever reason,
             the cookie will* be treated as a session cookie */
            cl->expires = curl_getdate(value, NULL);

            /* Session cookies have expires set to 0 so if we get that back
             f rom the date p*arser let's add a second to make it a
             non-session cookie */
            if(cl->expires == 0)
                cl->expires = 1;
            else if(cl->expires < 0)
                cl->expires = 0;

        }else if(strcmp(lowkey, "max-age") == 0){
            cl->maxage = value;
            cl->expires =
            strtol((*value=='\"')? &value[1]:&value[0], NULL, 10);
            if(CURL_OFF_T_MAX - now < cl->expires)
                /* avoid overflow */
                cl->expires = CURL_OFF_T_MAX;
            else
                cl->expires += now;

        }  else{
            cl->key = key;
            cl->value =value;
        }
        return ret;
    }

    char tempname[MAX_NAME];
    char oriname[MAX_NAME];
    char tempwhat[MAX_COOKIE_LINE];

    void _dealcookieLine(const char *buf, size_t len)
    {
        char *name = tempname, *what = tempwhat;
        char *orname = oriname;
        bool namestate = true;

        cookieLine *cl = new cookieLine;

        while (*buf && len-- > 0) {
            if(namestate){
                if (*buf != ' ' && *buf != '\t' && *buf != '\r' && *buf != '=' && *buf != ';') {
                    *name++ = tolower(*buf);
                    *orname++ = *buf;
                 } else if (*buf == '=') {
                    namestate = false;
                } else if (*buf == ';') {
                    *name = 0;
                    *orname = 0;
                    *what = 0;
                    dealapair(cl, tempname,oriname, tempwhat);
                    namestate = true;
                    name = tempname;
                    orname = oriname;
                    what = tempwhat;
                }
            }else{
                if (*buf == ';') {
                    *name = 0;
                    *orname = 0;
                    *what = 0;
                    dealapair(cl, tempname, oriname,tempwhat);
                    namestate = true;
                    name = tempname;
                    orname = oriname;
                    what = tempwhat;
                }else{
                    *what++ = *buf;
                }
            }
            buf++;
        }

        if(name != what){
            *name = 0;
            *orname = 0;
            *what = 0;
            dealapair(cl, tempname, oriname, tempwhat);
        }
        this->push_back(cl);
    }

    void parse(const char *parm){
        if(!parm){
            return;
        }
        
        const char *begin = parm, *end = NULL;
        char beginkey[] = "Set-Cookie:";
        size_t beginkeylen = sizeof(beginkey)-1;

        size_t i = 0, j = 0;
REPARSE:
        if(memcmp(begin, "HTTP/", 5)){
            return;
        }
        while(*begin != '\0'){
            while(*begin != '\r' && *begin != 'S' && *begin != '\0')  begin++;
            if(*begin == '\r'){
                if(begin[1] == '\n' && begin[2] == '\r' && begin[3] == '\n'){ //end of http header
                    begin+=4;
                    goto REPARSE; //incase of continue httpheader
                }
                begin++;
            }else if(*begin == 'S' || *begin == 's'){
                if(strncasecmp(begin, beginkey, beginkeylen) == 0){
                    if((end = strstr(begin, "\r\n"))){
                        _dealcookieLine(begin + 11, end-begin - 11);
                        begin = end;
                    }else{ //incomplete 
                        return;
                    }
                }else{
                    begin++;
                }
            }
        }
    }

};

class CHttpClient
{
private:
    static int OnDebug(CURL *, curl_infotype itype, char * pData, size_t , void *);
    static size_t OnWriteDataS(void* buffer, size_t size, size_t nmemb, void* lpVoid);
    static size_t OnWriteDataF(void* buffer, size_t size, size_t nmemb, void* lpVoid);
    bool m_bDebug;
    CURL* mCurl;
    CondMutex mCondMutex;

public:

    CHttpClient(void) :
    m_bDebug(false), userSysProxy(true){
        mCurl = curl_easy_init();
    }

    ~CHttpClient(void){
        if(mCurl){
            curl_easy_cleanup(mCurl);
        }
    }

    void reinit()
    {
        curl_easy_cleanup(mCurl);
        mCurl = curl_easy_init();
    }
public:
    /**
    * @brief HTTP POST请求
    * @param strUrl 输入参数,请求的Url地址,如:http://www.baidu.com
    * @param strPost 输入参数,使用如下格式para1=val1&val2&…
    * @param strResponse 输出参数,返回的内容
    * @param header
    vector<string> mHeader;
    mHeader.clear();
    mHeader.push_back("Accept:");
    mHeader.push_back("Connection: close");
    mHeader.push_back(string("User-Agent: Dalvik/2.1.0 (Linux; U; Android 5.1.1; LG-D802 Build/LMY48P) CocoVoice/87(zh-cn)[ver:7.4.3];[devkey:").append(mSession?mSession->getDeviceKey():"").append("];[devtype:Android]"));
    mHeader.push_back("Charset: UTF-8");
    mHeader.push_back(string("deviceId: ").append(mSession?mSession->getDeviceKey():""));
    mHeader.push_back("Content-Type: multipart/form-data;boundary=0xKhTmLbOuNdArY");
    mHeader.push_back("Accept-Encoding: gzip");
    mHeader.push_back("Content-Length: " + parmSize);
    * @return 返回是否Post成功
    */

    template <class T>
    int Post(const std::string & strUrl, const std::string & strPost, T & strResponse, CALLBACKFUN callback = NULL, vector<string> &header=*(vector<string> *)0)
    {
        CURLcode res = CURLE_FAILED_INIT;
        if (NULL == mCurl) {
            reinit();
        }
        mCondMutex.lock();

        curl_slist *http_headers = NULL;
        if (m_bDebug) {
            curl_easy_setopt(mCurl, CURLOPT_VERBOSE, 1);
            curl_easy_setopt(mCurl, CURLOPT_DEBUGFUNCTION, OnDebug);
        }
        if (&header != NULL) {
            for (vector<string>::iterator it = header.begin(); it != header.end(); it++) {
                http_headers = curl_slist_append(http_headers, it->c_str());
            }
            /* pass our list of custom made headers */
            curl_easy_setopt(mCurl, CURLOPT_HTTPHEADER, http_headers);
        }
        curl_easy_setopt(mCurl, CURLOPT_URL, strUrl.c_str());
        curl_easy_setopt(mCurl, CURLOPT_HEADER, 0);//head
        curl_easy_setopt(mCurl, CURLOPT_POST, 1);
        curl_easy_setopt(mCurl, CURLOPT_POSTFIELDS, strPost.c_str());
        curl_easy_setopt(mCurl, CURLOPT_READFUNCTION, NULL);
        if (typeid(strResponse) == typeid(string &)) {
            curl_easy_setopt(mCurl, CURLOPT_WRITEFUNCTION, OnWriteDataS);
        }
        else if (typeid(strResponse) == typeid(FILE* &)) {
            curl_easy_setopt(mCurl, CURLOPT_WRITEFUNCTION, OnWriteDataF);
        }
        else {
            printf("respone type error\n");
            goto END;
        }
        curl_easy_setopt(mCurl, CURLOPT_WRITEDATA, (void *)&strResponse);
        curl_easy_setopt(mCurl, CURLOPT_NOSIGNAL, 1);
        curl_easy_setopt(mCurl, CURLOPT_CONNECTTIMEOUT, 60);
        curl_easy_setopt(mCurl, CURLOPT_TIMEOUT, 120);
        curl_easy_setopt(mCurl, CURLOPT_FOLLOWLOCATION, 1);
        curl_easy_setopt(mCurl, CURLOPT_MAXREDIRS, -1);
        curl_easy_setopt(mCurl, CURLOPT_AUTOREFERER, 1);
        if (callback) {
            callback(mCurl);
        }
        if (userSysProxy) {
            sysproxy = GetSysProxy("");
            curl_easy_setopt(mCurl, CURLOPT_PROXY, sysproxy.c_str());
        }
        res = curl_easy_perform(mCurl);
    END:
        mCondMutex.unlock();
        if (http_headers) {
            curl_slist_free_all(http_headers); /* free the header list */
        }
        return res;

    }
    /**
    * @brief HTTP GET请求
    * @param strUrl 输入参数,请求的Url地址,如:http://www.baidu.com
    * @param strResponse 输出参数,返回的内容
    * @return 返回是否Post成功
    */
    template <class T>
    int Get(const std::string & strUrl, T & strResponse, 
        CALLBACKFUN callback = NULL, vector<string> &header = *(vector<string> *)0, bool keepalive = true)
    {
        CURLcode res = CURLE_FAILED_INIT;
        curl_slist *http_headers = NULL;

        if (NULL == mCurl) {
            reinit();
        }
        mCondMutex.lock();
        if (m_bDebug) {
            curl_easy_setopt(mCurl, CURLOPT_VERBOSE, 1);
            curl_easy_setopt(mCurl, CURLOPT_DEBUGFUNCTION, OnDebug);
        }

        if (&header != NULL) {
            for (vector<string>::iterator it = header.begin(); it != header.end(); it++) {
                http_headers = curl_slist_append(http_headers, it->c_str());
            }
            /* pass our list of custom made headers */
            curl_easy_setopt(mCurl, CURLOPT_HTTPHEADER, http_headers);
        }
        curl_easy_setopt(mCurl, CURLOPT_URL, strUrl.c_str());
        curl_easy_setopt(mCurl, CURLOPT_HTTPGET, 1);
        curl_easy_setopt(mCurl, CURLOPT_HEADER, 0);//head
        curl_easy_setopt(mCurl, CURLOPT_READFUNCTION, NULL);
        if (typeid(strResponse) == typeid(string &)) {
            curl_easy_setopt(mCurl, CURLOPT_WRITEFUNCTION, OnWriteDataS);
        }
        else if (typeid(strResponse) == typeid(FILE* &)) {
            curl_easy_setopt(mCurl, CURLOPT_WRITEFUNCTION, OnWriteDataF);
        }
        else {
            printf("respone type error\n");
            goto END;
        }
        curl_easy_setopt(mCurl, CURLOPT_WRITEDATA, (void *)&strResponse);
        curl_easy_setopt(mCurl, CURLOPT_NOSIGNAL, 1);
        curl_easy_setopt(mCurl, CURLOPT_CONNECTTIMEOUT, 60);
        curl_easy_setopt(mCurl, CURLOPT_TIMEOUT, 120);
        curl_easy_setopt(mCurl, CURLOPT_FOLLOWLOCATION, 1);
        curl_easy_setopt(mCurl, CURLOPT_MAXREDIRS, -1);
        curl_easy_setopt(mCurl, CURLOPT_AUTOREFERER, 1);
        if (callback) {
            callback(mCurl);
        }
        if (userSysProxy) {
            sysproxy = GetSysProxy("");
            curl_easy_setopt(mCurl, CURLOPT_PROXY, sysproxy.c_str());
        }
        res = curl_easy_perform(mCurl);
    END:
        if (!keepalive) {
            curl_easy_cleanup(mCurl);
            mCurl = NULL;
        }
        mCondMutex.unlock();
        if (http_headers != NULL) {
            curl_slist_free_all(http_headers); /* free the header list */
        }
        return res;
    }

    /**
    * @brief HTTPS POST请求,无证书版本
    * @param strUrl 输入参数,请求的Url地址,如:https://www.alipay.com
    * @param strPost 输入参数,使用如下格式para1=val1&para2=val2&…
    * @param strResponse 输出参数,返回的内容
    * @param pCaPath 输入参数,为CA证书的路径.如果输入为NULL,则不验证服务器端证书的有效性.
    * @return 返回是否Post成功
    */
    template <class T>
    int Posts(const std::string & strUrl, const std::string & strPost, T & strResponse, const char * pCaPath = NULL, CALLBACKFUN callback = NULL, vector<string> &header=*(vector<string> *)0)
    {
        CURLcode res = CURLE_FAILED_INIT;
        if (NULL == mCurl) {
            reinit();
        }
        mCondMutex.lock();

        curl_slist *http_headers = NULL;
        if (m_bDebug) {
            curl_easy_setopt(mCurl, CURLOPT_VERBOSE, 1);
            curl_easy_setopt(mCurl, CURLOPT_DEBUGFUNCTION, OnDebug);
        }
        if (&header != NULL) {
            for (vector<string>::iterator it = header.begin(); it != header.end(); it++) {
                http_headers = curl_slist_append(http_headers, it->c_str());
            }
            /* pass our list of custom made headers */
            curl_easy_setopt(mCurl, CURLOPT_HTTPHEADER, http_headers);
        }
        curl_easy_setopt(mCurl, CURLOPT_URL, strUrl.c_str());
        curl_easy_setopt(mCurl, CURLOPT_HEADER, 0);//head
        curl_easy_setopt(mCurl, CURLOPT_POST, 1);
        curl_easy_setopt(mCurl, CURLOPT_POSTFIELDS, strPost.c_str());
        curl_easy_setopt(mCurl, CURLOPT_READFUNCTION, NULL);
        if (typeid(strResponse) == typeid(string &)) {
            curl_easy_setopt(mCurl, CURLOPT_WRITEFUNCTION, OnWriteDataS);
        }
        else if (typeid(strResponse) == typeid(FILE* &)) {
            curl_easy_setopt(mCurl, CURLOPT_WRITEFUNCTION, OnWriteDataF);
        }
        else {
            printf("respone type error\n");
            goto END;
        }
        curl_easy_setopt(mCurl, CURLOPT_WRITEDATA, (void *)&strResponse);
        curl_easy_setopt(mCurl, CURLOPT_NOSIGNAL, 1);

        if (NULL == pCaPath) {
            curl_easy_setopt(mCurl, CURLOPT_SSL_VERIFYPEER, false);
            curl_easy_setopt(mCurl, CURLOPT_SSL_VERIFYHOST, false);
        }
        else {
            //缺省情况就是PEM，所以无需设置，另外支持DER
            //curl_easy_setopt(curl,CURLOPT_SSLCERTTYPE,"PEM");
            curl_easy_setopt(mCurl, CURLOPT_SSL_VERIFYPEER, true);
            curl_easy_setopt(mCurl, CURLOPT_CAINFO, pCaPath);
        }
        curl_easy_setopt(mCurl, CURLOPT_CONNECTTIMEOUT, 60);
        curl_easy_setopt(mCurl, CURLOPT_TIMEOUT, 120);
        curl_easy_setopt(mCurl, CURLOPT_FOLLOWLOCATION, 1);
        curl_easy_setopt(mCurl, CURLOPT_MAXREDIRS, -1);
        curl_easy_setopt(mCurl, CURLOPT_AUTOREFERER, 1);
        if (callback) {
            callback(mCurl);
        }
        if (userSysProxy) {
            sysproxy = GetSysProxy("");
            curl_easy_setopt(mCurl, CURLOPT_PROXY, sysproxy.c_str());
        }
        res = curl_easy_perform(mCurl);
    END:
        mCondMutex.unlock();
        if (http_headers) {
            curl_slist_free_all(http_headers); /* free the header list */
        }
        return res;

    }
    /**
    * @brief HTTPS GET请求,无证书版本
    * @param strUrl 输入参数,请求的Url地址,如:https://www.alipay.com
    * @param strResponse 输出参数,返回的内容
    * @param pCaPath 输入参数,为CA证书的路径.如果输入为NULL,则不验证服务器端证书的有效性.
    * @callback example:
        void setcrawlExtra(CURL* curl)
        {
            curl_easy_setopt(curl, CURLOPT_COOKIEFILE,"cookie_open.txt");
        }
    * @return 返回是否Post成功
    */

    template <class T>
    int Gets(const std::string & strUrl, T & strResponse,
             const char * pCaPath = NULL, CALLBACKFUN callback = NULL, vector<string> &header= *(vector<string> *)0, bool keepalive = true)
    {
        CURLcode res = CURLE_FAILED_INIT;
        curl_slist *http_headers = NULL;

        if (NULL == mCurl) {
            reinit();
        }
        mCondMutex.lock();
        if (m_bDebug) {
            curl_easy_setopt(mCurl, CURLOPT_VERBOSE, 1);
            curl_easy_setopt(mCurl, CURLOPT_DEBUGFUNCTION, OnDebug);
        }
        if (&header != NULL) {
            for (vector<string>::iterator it = header.begin(); it != header.end(); it++) {
                http_headers = curl_slist_append(http_headers, it->c_str());
            }
            /* pass our list of custom made headers */
            curl_easy_setopt(mCurl, CURLOPT_HTTPHEADER, http_headers);
        }
        curl_easy_setopt(mCurl, CURLOPT_URL, strUrl.c_str());
        curl_easy_setopt(mCurl, CURLOPT_HTTPGET, 1);
        curl_easy_setopt(mCurl, CURLOPT_HEADER, 0);//head
        curl_easy_setopt(mCurl, CURLOPT_READFUNCTION, NULL);
        if (typeid(strResponse) == typeid(string &)) {
            curl_easy_setopt(mCurl, CURLOPT_WRITEFUNCTION, OnWriteDataS);
        }
        else if (typeid(strResponse) == typeid(FILE* &)) {
            curl_easy_setopt(mCurl, CURLOPT_WRITEFUNCTION, OnWriteDataF);
        }
        else {
            printf("respone type error\n");
            goto END;
        }
        curl_easy_setopt(mCurl, CURLOPT_WRITEDATA, (void *)&strResponse);
        curl_easy_setopt(mCurl, CURLOPT_NOSIGNAL, 1);

        if (NULL == pCaPath) {
            curl_easy_setopt(mCurl, CURLOPT_SSL_VERIFYPEER, false);
            curl_easy_setopt(mCurl, CURLOPT_SSL_VERIFYHOST, false);
        }
        else {
            curl_easy_setopt(mCurl, CURLOPT_SSL_VERIFYPEER, true);
            curl_easy_setopt(mCurl, CURLOPT_CAINFO, pCaPath);
        }
        curl_easy_setopt(mCurl, CURLOPT_CONNECTTIMEOUT, 60);
        curl_easy_setopt(mCurl, CURLOPT_TIMEOUT, 120);
        curl_easy_setopt(mCurl, CURLOPT_FOLLOWLOCATION, 1);
        curl_easy_setopt(mCurl, CURLOPT_MAXREDIRS, -1);
        curl_easy_setopt(mCurl, CURLOPT_AUTOREFERER, 1);
        if (callback) {
            callback(mCurl);
        }
        if (userSysProxy) {
            sysproxy = GetSysProxy("");
            curl_easy_setopt(mCurl, CURLOPT_PROXY, sysproxy.c_str());
        }
        res = curl_easy_perform(mCurl);
        //getContentType();
    END:
        if (!keepalive) {
            curl_easy_cleanup(mCurl);
            mCurl = NULL;
        }
        mCondMutex.unlock();
        if (http_headers != NULL) {
            curl_slist_free_all(http_headers); /* free the header list */
        }

        return res;

    }

    void SetDebug(bool bDebug);

/*
Pass a char * argument specifying what encoding you'd like.

Sets the contents of the Accept-Encoding: header sent in a HTTP request,
and enables decoding of a response when a Content-Encoding: header is received.

Three encodings are supported:
    identity, meaning non-compressed,
    deflate which requests the server to compress its response using the zlib algorithm,
    and gzip which requests the gzip algorithm.
    If a zero-length string is set like "",
    then an Accept-Encoding: header containing all built-in supported encodings is sent.

Set this option to NULL to explicitly disable it, which makes libcurl not send an Accept-Encoding: header and not decompress contents automatically.

You can also opt to just include the Accept-Encoding: header in your request with CURLOPT_HTTPHEADER but then there will be no automatic decompressing when receiving data.

This is a request, not an order; the server may or may not do it. This option must be set (to any non-NULL value) or else any unsolicited encoding done by the server is ignored.

Servers might respond with Content-Encoding even without getting a Accept-Encoding: in the request. Servers might respond with a different Content-Encoding than what was asked for in the request.

The Content-Length: servers send for a compressed response is supposed to indicate the length of the compressed content so when auto decoding is enabled it may not match the sum of bytes reported by the write callbacks (although, sending the length of the non-compressed content is a common server mistake).
*/
    int setAutoDecoding(const char *enc)
    {
        if(NULL == mCurl){
            return CURLE_FAILED_INIT;
        }

        CURLcode ret =curl_easy_setopt(mCurl, CURLOPT_ACCEPT_ENCODING, enc);
        return ret;
    }

    void getContentType()
    {
        char *contentType={0};
        int return_code = curl_easy_getinfo(mCurl, CURLINFO_CONTENT_TYPE , &contentType);
        if((CURLE_OK==return_code) && contentType)
            printf("======%s====\n", contentType);
    }



/*

    int put()
    {

        curl_easy_setopt(mCurl,CURLOPT_URL,url);  //关键的来了，设置URL
        curl_easy_setopt(mCurl,CURLOPT_PUT,1L); //使用PUT请求
        //curl_easy_setopt(mCurl,CURLOPT_READFUNCTION,put_data); //设置上传数据回调函数
        //curl_easy_setopt(mCurl,CURLOPT_READDATA,fp); //设置上传文件的FILE指针
        curl_easy_setopt(mCurl,CURLOPT_INFILESIZE,len); //设置上传文件的大小

        code=curl_easy_perform(curl); //设置完成，开始发送请求
        fclose(fp);
        free(url);
        printf("%d\n",code);

        getchar();
        url=get_url(argv[1],"DELETE");
        curl_easy_setopt(curl,CURLOPT_PUT,0L); //关闭PUT请求设置
        curl_easy_setopt(curl,CURLOPT_CUSTOMREQUEST,"DELETE"); //设置DELETE请求
        curl_easy_setopt(curl,CURLOPT_URL,url);

        code=curl_easy_perform(curl); //发送DELETE请求
        free(url);
        printf("%d\n",code);

        curl_easy_cleanup(curl);

        return 0;
    }
*/
    private:
        bool userSysProxy;
        string sysproxy;
};


#endif // CHTTPCLIENT_H
